﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MoLib
{
    public class MoParser : IDisposable
    {
        public const uint ByteOrderOne = 0x950412de;
        public const uint ByteOrderTwo = 0xde120495;

        private BinaryReader _reader;
        private Stream _stream;

        private Dictionary<string, string> _fileDictionary;
        public Dictionary<string, string> FileDictionary
        {
            get
            {
                if (_fileDictionary == null)
                {
                    uint byteOrder = _reader.ReadUInt32();
                    ushort majorRevision = _reader.ReadUInt16();
                    ushort minorRevision = _reader.ReadUInt16();
                    uint numberOfStrings = _reader.ReadUInt32();
                    uint originalStringsOffset = _reader.ReadUInt32();
                    uint translationStringsOffset = _reader.ReadUInt32();
                    uint sizeOfHashingTable = _reader.ReadUInt32();
                    uint offsetOfHashingTable = _reader.ReadUInt32();

                    string[] keyStrings = GetStrings(numberOfStrings, originalStringsOffset);
                    string[] valueStrings = GetStrings(numberOfStrings, translationStringsOffset);
                    Dictionary<string, string> results = new Dictionary<string, string>(keyStrings.Length);

                    for (int i = 0; i < keyStrings.Length; i++)
                    {
                        results.Add(keyStrings[i], valueStrings[i]);
                    }

                    _fileDictionary = results;
                }

                return _fileDictionary;
            }
        }

        public MoParser(string fileName)
        {
            _stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            _reader = new BinaryReader(_stream);
        }

        public MoParser(Stream stream)
        {
            _stream = stream;
            _reader = new BinaryReader(_stream);
        }

        public MoParser(BinaryReader reader)
        {
            _reader = reader;
            _stream = reader.BaseStream;
        }

        public void Dispose()
        {
            _reader.Dispose();
            _stream.Dispose();
        }

        private string[] GetStrings(uint numberOfStrings, uint offset)
        {
            List<string> strings = new List<string>();
            for (uint i = 0; i < numberOfStrings; i++)
            {
                _stream.Seek(offset + (i * 8), SeekOrigin.Begin);

                uint keyStringLength = _reader.ReadUInt32();
                uint keyStringOffset = _reader.ReadUInt32();

                _stream.Seek(keyStringOffset, SeekOrigin.Begin);

                byte[] keyStringBytes = _reader.ReadBytes((int)keyStringLength);
                string keyString = Encoding.UTF8.GetString(keyStringBytes);
                strings.Add(keyString);
            }
            return strings.ToArray();
        }
    }
}
